package org.opencv.LoadObj;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
//import android.view.Menu;
//import android.view.MenuItem;
import android.util.Log;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast;
import android.widget.TextView;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

//import java.text.SimpleDateFormat;
//import java.util.Date;

import org.opencv.android.BaseLoaderCallback;
//import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.core.Rect;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;

import com.bieyang.anjia.R;

public class DetectObjActivity extends Activity implements CvCameraViewListener2,SensorEventListener{

	private static final String TAG = "Opencv:LoadObj";
	private Mat					mRGBA;
	private Mat					mGray;
	private boolean					mDetectFlag = false;
	private LoadObjDetector		mNativeDetector;

	// References to SensorManager and accelerometer
	private SensorManager mSensorManager;
	private Sensor mAccelerometer;
	private TextView mXAccelView, mYAccelView, mZAccelView;
	private long mLastUpdate;
	private final float mAlpha = 0.8f;
	// Arrays for storing filtered values
	private float[] mGravity = new float[3];
	private float[] mAccel = new float[3];
	
	private CameraCtrlView	mCameraView;
	private boolean			m_DetectEnable = false;
	private static final Scalar 	OBJ_RECT_COLOR = new Scalar(0,255,0,255);
	private static final Scalar		Debug_Rect_Color = new Scalar(255,255,255,255);
	private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this){
		@Override
		public void onManagerConnected(int status){
			switch(status){
				case LoaderCallbackInterface.SUCCESS:
				{
					Log.i(TAG,"Load Opencv successfully!");
					
					// Load native Library
					//System.loadLibrary("LoadObjDetector");
					
					
					//mCameraView.enableView();
					//Log.i(TAG,"Reset resolution enter");
					//mCameraView.setResolution();
					//Log.i(TAG,"Reset resolution finish");
					//mNativeDetector = new LoadObjDetector();
					//mCameraView.enableView();
					//mCameraView.setOnTouchListener(DetectObjActivity.this);
				}break;
				default:
				{
					super.onManagerConnected(status);
				}break;
			}
		}
	};
	
	public DetectObjActivity(){
		Log.i(TAG,"Instantiated new"+this.getClass());
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.i(TAG,"called onCreate");
		super.onCreate(savedInstanceState);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		setContentView(R.layout.sub_detect_obj);
		
		mCameraView = (CameraCtrlView)findViewById(R.id.LoadObj_activity_surface_View);
		mCameraView.setVisibility(SurfaceView.VISIBLE);
		//m_resolution = new Size(1920,1080);
		mCameraView.setCvCameraViewListener(this);
		
		
		mXAccelView = (TextView) findViewById(R.id.x_highpass_view);
		mYAccelView = (TextView) findViewById(R.id.y_highpass_view);
		mZAccelView = (TextView) findViewById(R.id.z_highpass_view);
	
		// Get reference to SensorManager
		mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

		// Get reference to Accelerometer
		if (null == (mAccelerometer = mSensorManager
				.getDefaultSensor(Sensor.TYPE_ACCELEROMETER))){
			Log.i(TAG,"Sensor Service failed!");
			finish();
		}

		mLastUpdate = System.currentTimeMillis();
	}
	
	@Override
	public void onPause(){
		super.onPause();
		if (mCameraView!=null)
			mCameraView.disableView();
		
		mSensorManager.unregisterListener(this);
	}
	
	@Override
	public void onResume(){
		super.onResume();
//		OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_8, this, mLoaderCallback);

		
		if (OpenCVLoader.initDebug()){
        	//mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        	Log.i(TAG,"OPENCV Static Initialization");
        	System.loadLibrary("opencv_java");
    		
        	
        }else{
        	Log.i(TAG,"Static Initialization failed");
        }

		System.loadLibrary("LoadObjDetector");
		mCameraView.setResolution();
		mNativeDetector = new LoadObjDetector();
		mCameraView.enableView();
		//mCameraView.setResolution();
		
		mSensorManager.registerListener(this, mAccelerometer,
				SensorManager.SENSOR_DELAY_UI);
	}
	
	@Override
	public void onDestroy(){
		super.onDestroy();
		mCameraView.disableView();
		mNativeDetector.release();
	}
	
	public void onCameraViewStarted(int width,int height){
		Log.i(TAG,"WIDTH: "+width+",HEIGHT: "+height);
		mGray = new Mat();
		mRGBA = new Mat();
		mNativeDetector.InitObj(width,height);
		mDetectFlag = true;
	}
	
	public void onCameraViewStopped(){
		mGray.release();
		mRGBA.release();
	}
	
	public Mat onCameraFrame(CvCameraViewFrame inputFrame){
		mRGBA = inputFrame.rgba();
		//mGray = inputFrame.gray();
		MatOfRect objMat = new MatOfRect();
		MatOfRect borderMat = new MatOfRect();
		/*
		mNativeDetector.detect(mRGBA,objMat);
		if (objMat.empty()) {
			//Log.i(TAG,"backGround Update...");
			return mRGBA;
		}
		*/
		if (mNativeDetector.motionDetect(mRGBA))
			Core.putText(mRGBA,"WARNING:Motion Target!",new Point(200,30),0,1.0,new Scalar(200,0,200,255));
		
		mNativeDetector.BorderAlarm(mRGBA,borderMat);
		Rect []objArray = objMat.toArray();
		for (int i = 0;i<objArray.length;i++)
			Core.rectangle(mRGBA, objArray[i].tl(), objArray[i].br(),OBJ_RECT_COLOR,3);
		
		return mRGBA;
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// NA
	}
    
    @Override
	public void onSensorChanged(SensorEvent event) {

    	if (mDetectFlag==false)
    		return;
		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

			long actualTime = System.currentTimeMillis();
			
			if (actualTime - mLastUpdate > 100) {

				mLastUpdate = actualTime;

				float rawX = event.values[0];
				float rawY = event.values[1];
				float rawZ = event.values[2];
				
				// Apply low-pass filter
				mGravity[0] = lowPass(rawX, mGravity[0]);
				mGravity[1] = lowPass(rawY, mGravity[1]);
				mGravity[2] = lowPass(rawZ, mGravity[2]);
				
				// Apply high-pass filter
				mAccel[0] = highPass(rawX, mGravity[0]);
				mAccel[1] = highPass(rawY, mGravity[1]);
				mAccel[2] = highPass(rawZ, mGravity[2]);
				
				//mXValueView.setText(String.valueOf(rawX));
				//mYValueView.setText(String.valueOf(rawY));
				//mZValueView.setText(String.valueOf(rawZ));
				
				if(mAccel[0]>0.3||mAccel[1]>0.3||mAccel[2]>0.3){
					if (mNativeDetector.IsSensorEnable()){
						mNativeDetector.BGResetShake();
						mXAccelView.setText(String.valueOf(mAccel[0]));
						mYAccelView.setText(String.valueOf(mAccel[1]));
						mZAccelView.setText(String.valueOf(mAccel[2]));
					}
					
					
				}else{
					mXAccelView.setText(String.valueOf(0.0));
					mYAccelView.setText(String.valueOf(0.0));
					mZAccelView.setText(String.valueOf(0.0));
				}
				
			}
		}
		
	}
    
 // Deemphasize transient forces
 	private float lowPass(float current, float gravity) {

 		return gravity * mAlpha + current * (1 - mAlpha);

 	}
 	
	// Deemphasize constant forces
	private float highPass(float current, float gravity) {

		return current - gravity;

	}
	
}
